﻿// This is an open source non-commercial project. Dear PVS-Studio, please check it.
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com

// ReSharper disable CheckNamespace
// ReSharper disable CommentTypo

/* SourceGeneratorOptions.cs -- опции
 * Ars Magna project, http://arsmagna.ru
 */

#region Using directives

using System;
using System.Collections.Generic;
using System.IO;

using Microsoft.CodeAnalysis;

#endregion

namespace AM.SourceGeneration
{
    /// <summary>
    /// Опции.
    /// </summary>
    internal sealed class SourceGeneratorOptions<TGenerator>
        where TGenerator : ISourceGenerator
    {
        public SourceGeneratorOptions
            (
                GeneratorExecutionContext context
            )
        {
            if (TryReadGlobalOption (context, "SourceGenerator_EnableLogging", out var enableLogging) &&
                bool.TryParse (enableLogging, out var enableLoggingValue))
            {
                EnableLogging = enableLoggingValue;
            }

            if (TryReadGlobalOption (context, "SourceGenerator_DetailedLog", out var detailedLog) &&
                bool.TryParse (detailedLog, out var detailedLogValue))
            {
                DetailedLogging = detailedLogValue;
            }

            if (TryReadGlobalOption (context, "SourceGenerator_LogPath", out var logPath))
            {
                LogPath = logPath;
            }
            else
            {
                var directory = Path.Combine (Directory.GetCurrentDirectory(), "obj");
                LogPath = Path.Combine (directory, $"{typeof (TGenerator).Name}.log");
            }

            if (TryReadGlobalOption (context, "SourceGenerator_IntellisenseFix", out var intellisenseFix) &&
                bool.TryParse (intellisenseFix, out var intellisenseFixValue))
            {
                IntellisenseFix = intellisenseFixValue;
            }

            if (TryReadGlobalOption (context, "IntermediateOutputPath", out var intermediate))
            {
                IntermediateOutputPath = intermediate;
            }
            else
            {
                throw new NotSupportedException();
            }

            if (TryReadGlobalOption (context, "SourceGenerator_EnableDebug", out var enableDebug) &&
                bool.TryParse (enableDebug, out var enableDebugValue))
            {
                EnableDebug = enableDebugValue;
            }

            if (TryReadGlobalOption (context, $"SourceGenerator_EnableDebug_{typeof (TGenerator).Name}",
                    out var debugThisGenerator) && bool.TryParse (debugThisGenerator, out var debugThisGeneratorValue))
            {
                EnableDebug = debugThisGeneratorValue;
            }

            foreach (var file in context.AdditionalFiles)
            {
                if (TryReadAdditionalFilesOption (context, file, "Type", out var type))
                {
                    AdditionalFilesOptions.Add (new AdditionalFilesOptions
                    {
                        Type = type,
                        AdditionalText = file
                    });
                }
            }
        }

        public bool EnableLogging { get; set; }

        public bool DetailedLogging { get; set; }

        public bool EnableDebug { get; set; }

        public string LogPath { get; set; }

        public bool IntellisenseFix { get; set; }

        public string IntermediateOutputPath { get; set; }

        public List<AdditionalFilesOptions> AdditionalFilesOptions { get; set; } = new List<AdditionalFilesOptions>();

        public bool TryReadGlobalOption
            (
                GeneratorExecutionContext context,
                string property,
                out string value
            )
            => context.AnalyzerConfigOptions.GlobalOptions.TryGetValue ($"build_property.{property}", out value!);

        public bool TryReadAdditionalFilesOption
            (
                GeneratorExecutionContext context,
                AdditionalText additionalText,
                string property,
                out string value
            )
        {
            return context.AnalyzerConfigOptions.GetOptions (additionalText)
                .TryGetValue ($"build_metadata.AdditionalFiles.{property}", out value!);
        }
    }
}
